package com.why.cachecloud.util;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Slf4j
public class DingDingUtil {
    //发送超时时间10s
    private static final int TIME_OUT = 10000;
    private static final String MSGTYPEZ = "msgtype";
    private static final String MARKDOWN = "markdown";
    private static final String TITLE = "title";
    private static final String TEXT = "text";
    private static final String ATMOBILES = "atMobiles";
    private static final String ISATALL = "isAtAll";
    private static final String AT = "at";

    /**
     * @param webhook
     * @param secret    安全设置 3选1【方式一，自定义关键词 】 【方式二，加签 ，创建机器人时选择加签 secret以SE开头】【方式三，IP地址（段）】
     * @param content   发送内容
     * @param phoneList 通知具体人的手机号码列表 （可选）
     * @return
     */
    public static void sendMsg(String webhook, String accessToken, String secret, String content, List<String> phoneList) {
        try {
            //钉钉机器人地址（配置机器人的webhook）
            if (!StringUtils.isEmpty(secret)) {
                Long timestamp = System.currentTimeMillis();
                String sign = getSign(timestamp, secret);
                webhook = webhook + "?access_token=" + accessToken + "&timestamp=" + timestamp + "&sign=" + sign;
            }
            //是否通知所有人
            boolean isAtAll = false;
            //组装请求内容
            String reqStr = buildReqMarkDown(content, isAtAll, phoneList);
            //推送消息（http请求）
            String result = postJson(webhook, reqStr);
            JSONObject jsonObject = JsonUtil.fromJson(result, JSONObject.class);
            if (jsonObject.getInteger("errcode") != 0) {
                log.error("调用钉钉机器人接口失败,错误信息：{}", jsonObject.getString("errmsg"));
            }
        } catch (Exception e) {
            log.error("发送群通知异常", e);
        }
    }

    /**
     * 组装请求报文
     * 发送消息类型 markdown
     * @link https://open.dingtalk.com/document/group/custom-robot-access
     */
    private static String buildReqMarkDown(String content, boolean isAtAll, List<String> mobileList) {
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put(MSGTYPEZ, MARKDOWN);
        HashMap<String, String> markdownMap = new HashMap<>();
        markdownMap.put(TITLE, ConstUtils.NOTICE_TITLE);
        markdownMap.put(TEXT, content);
        resultMap.put(MARKDOWN, markdownMap);
        HashMap<String, Object> atMap = new HashMap<>();
        atMap.put(ATMOBILES, mobileList);
        atMap.put(ISATALL, isAtAll);
        resultMap.put(AT, atMap);
        return JSON.toJSONString(resultMap);
    }


    private static String postJson(String url, String reqStr) {
        return HttpRequest.post(url).body(reqStr).timeout(TIME_OUT).executeAsync().body();
    }

    /**
     * 自定义机器人获取签名
     * 创建机器人时选择加签获取secret以SE开头
     *
     * @param timestamp
     * @return
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     */
    private static String getSign(Long timestamp, String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        String stringToSign = timestamp + "\n" + secret;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
        return URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
    }


    public static void main(String[] args) {
        String webhook = "https://oapi.dingtalk.com/robot/send";
        String accessToken = "1cfc57a29fdf35fb23e0393101bf4474a19b5822ffb6ca757be510935a58f5ab";
        String secret = "SECbbe721e81e28f1f209289924ab6a74019e618967d97e3110595c468674e63714";
        List<String> phoneList = new ArrayList<>();
        phoneList.add("18003737030");
        DingDingUtil.sendMsg(webhook, accessToken, secret, "CacheCloud系统-客户端连接数报警\n\n应用(%s)-客户端连接数报警-预设阀值每个分片为%s-现已达到%s(分片个数:%s)-请及时关注", phoneList);
    }
}
